﻿using System;
using NUnit.Framework;
using TechTalk.SpecFlow;

namespace Matrix.Data.Tests
{
    [Binding]
    public class MatrixData_TC01_Steps
    {
       private class Exceptionable
       {
          public object Value { get; set; }
          public Type ExpectedExceptionType { get; set; }
       }

       #region TC01a
       [When(@"I request a Matrix object of (.*) rows and (.*) columns")]
       public void WhenIRequestAMatrixObjectOfRowsAndColumns(int rows, int cols)
       {
          ScenarioContext.Current["Matrix"] = new Matrix(rows, cols);
       }
       #endregion // TC01a

       #region TC01b
       [Given(@"I have selected the (.*) test string")]
       public void GivenIHaveSelectedTheTestString(int index)
       {
          const string CRLF = "\r\n";
          Exceptionable testObject = null;
          switch (index)
          {
             case 1:
                testObject =
                   new Exceptionable
                      {
                         Value = "1 2 3" + CRLF +
                                 "4 5 6" + CRLF +
                                 "7 8 9",
                         ExpectedExceptionType = null
                      };
                break;
             case 2:
                testObject =
                   new Exceptionable
                      {
                         Value = "1 2 3," + CRLF +
                                 "1 2 3," + CRLF +
                                 "1 2 3",
                         ExpectedExceptionType = null
                      };
                break;
             case 3:
                testObject =
                   new Exceptionable
                   {
                      Value = "[1 2 3]" + CRLF +
                              "[1 2 3]" + CRLF +
                              "[1 2 3]",
                      ExpectedExceptionType = typeof(MatrixException)
                   };
                break;
             case 4:
                testObject =
                   new Exceptionable
                   {
                      Value = "1" + CRLF +
                              "1 2" + CRLF +
                              "1 2 3",
                      ExpectedExceptionType = null
                   };
                break;
             case 5:
                testObject =
                   new Exceptionable
                   {
                      Value = "1 2 3" + CRLF +
                              "1 2" + CRLF +
                              "1",
                      ExpectedExceptionType = null
                   };
                break;
             case 6:
                testObject =
                   new Exceptionable
                   {
                      Value = "a b c" + CRLF +
                              "a b c" + CRLF +
                              "a b c",
                      ExpectedExceptionType = typeof(MatrixException)
                   };
                break;
             case 7:
                testObject =
                   new Exceptionable
                   {
                      Value = "1 2 3 4 5 6 7 8 9",
                      ExpectedExceptionType = null
                   };
                break;
             case 8:
                testObject =
                   new Exceptionable
                   {
                      Value = "1" + CRLF +
                              "2" + CRLF +
                              "3" + CRLF +
                              "4" + CRLF +
                              "5",
                      ExpectedExceptionType = null
                   };
                break;
             case 9:
                testObject =
                   new Exceptionable
                   {
                      Value = "11111aaaaa222222bbbb",
                      ExpectedExceptionType = typeof(MatrixException)
                   };
                break;
             case 10:
                testObject =
                   new Exceptionable
                   {
                      Value = string.Empty,
                      ExpectedExceptionType = typeof(MatrixException)
                   };
                break;
             case 11:
                testObject =
                   new Exceptionable
                   {
                      Value = "-1 -2" + CRLF +
                              "-3 -4",
                      ExpectedExceptionType = null
                   };
                break;
             case 12:
                testObject =
                   new Exceptionable
                   {
                      Value = "-1.01 -2.02" + CRLF +
                              "-3.03 -4.04",
                      ExpectedExceptionType = null
                   };
                break;
             case 13:
                testObject =
                   new Exceptionable
                   {
                      Value = "1.001 2.002" + CRLF +
                              "3.003 4.004",
                      ExpectedExceptionType = null
                   };
                break;
             case 14:
                testObject =
                   new Exceptionable
                   {
                      Value = "-1.01 2.02" + CRLF +
                              "-3 4.04",
                      ExpectedExceptionType = null
                   };
                break;
             case 15:
                testObject =
                   new Exceptionable
                   {
                      Value = "+1.01 -2.02" + CRLF +
                              "+3 +4",
                      ExpectedExceptionType = null
                   };
                break;
             case 16:
                testObject =
                   new Exceptionable
                   {
                      Value = "1 2 3" + CRLF +
                              "1" + CRLF +
                              "1 2",
                      ExpectedExceptionType = null
                   };
                break;
             case 17:
                testObject =
                   new Exceptionable
                   {
                      Value = "1 2 3" + CRLF +
                              "" + CRLF +
                              "1 2 3",
                      ExpectedExceptionType = null
                   };
                break;
             case 18:
                testObject =
                   new Exceptionable
                   {
                      Value = "" + CRLF +
                              "1 2 3" + CRLF +
                              "1 2 3",
                      ExpectedExceptionType = null
                   };
                break;
             case 19:
                testObject =
                   new Exceptionable
                   {
                      Value = "1 2" + CRLF +
                              "1" + CRLF +
                              "1 2 3",
                      ExpectedExceptionType = null
                   };
                break;
             case 20:
                testObject =
                   new Exceptionable
                   {
                      Value = "1 2 3," + CRLF +
                              "," + CRLF +
                              "1 2 3",
                      ExpectedExceptionType = null
                   };
                break;
             case 21:
                testObject =
                   new Exceptionable
                   {
                      Value = "," + CRLF +
                              "1 2 3," + CRLF +
                              "1 2 3",
                      ExpectedExceptionType = null
                   };
                break;
          }
          ScenarioContext.Current["testObject"] = testObject;
          ScenarioContext.Current["testString"] = testObject.Value as string;
       }

       [When(@"the Matrix library parses this string")]
       public void WhenTheMatrixLibraryParsesThisString()
       {
          var testString = ScenarioContext.Current["testString"] as string;

          object o;
          var testObject = ScenarioContext.Current.TryGetValue("testObject", out o) ? o as Exceptionable : null;
          if (testObject != null)
          {
             if (testObject.ExpectedExceptionType != null)
             {
                Assert.That(delegate { ScenarioContext.Current["Matrix"] = Matrix.Parse(testString); },
                            Throws.TypeOf(testObject.ExpectedExceptionType));
                Assert.Pass("The Matrix library did not allow an improperly formatted string to become a Matrix object."); 
             }
             else
             {
                Assert.That(delegate { ScenarioContext.Current["Matrix"] = Matrix.Parse(testString); }, Throws.Nothing);
             }
          }
          else
          {
             ScenarioContext.Current["Matrix"] = Matrix.Parse(testString);
          }
       }
       #endregion // TC01b

       [Then(@"the Matrix object should not be null")]
       public void ThenTheMatrixObjectShouldNotBeNull()
       {
          object o;
          var testObject = ScenarioContext.Current.TryGetValue("testObject", out o) ? o as Exceptionable : null;
          if ((testObject == null) || (testObject.ExpectedExceptionType == null))
          {
             Assert.IsNotNull(ScenarioContext.Current["Matrix"], "The square Matrix was not created!!!");
             Assert.IsInstanceOf(typeof(Matrix), ScenarioContext.Current["Matrix"]);
          }
       }
    }
}
